#include "stdafx.h"
#include "ref_counter.h"

namespace async_curl {
	ref_counter::ref_counter(const ref_counter & o)
		:counter_(o.counter_), cb_(o.cb_) {
		counter_->fetch_add(1ll);
	}

	ref_counter::ref_counter(ref_counter &&o)
		: counter_(o.counter_), cb_(std::move(o.cb_)) {
		o.counter_ = nullptr;
		o.cb_ = nullptr;
	}

	ref_counter::ref_counter(ref_counter_cb_t&& cb)
		: counter_(new counter_t(1)), cb_(std::forward<ref_counter_cb_t>(cb)) {}

	ref_counter& ref_counter::operator=(const ref_counter &o) {
		if (this == &o || counter_ == o.counter_) {
			return *this;
		}
		decrease();
		o.counter_->fetch_add(1ll);
		counter_ = o.counter_;
		return *this;
	}

	ref_counter& ref_counter::operator=(ref_counter &&o) {
		if (this == &o || counter_ == o.counter_) {
			assert(false);//for debug
			return *this;
		}
		decrease();
		o.counter_ = nullptr;
		cb_ = std::move(o.cb_);
		return *this;
	}

	ref_counter::~ref_counter() {
		if (counter_ == nullptr || !(bool)cb_) {
			return;
		}
		decrease();
	}

	void ref_counter::decrease() {
		if (counter_->fetch_add(-1ll) == 1) {
			delete counter_;
			//reach 0
			cb_();
		}
	}
}
